﻿//+------------------------------------------------------------------+
//|                                             MetaTrader 5 Web API |
//|                   Copyright 2001-2015, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using MetaQuotes.MT5WebAPI.Common.Utils;
using Newtonsoft.Json;
//---
namespace MetaQuotes.MT5WebAPI.Common.Protocol
{
    /// <summary>
    /// Send common_get to MetaTrader 5 Server
    /// </summary>
    class MTCommonBase : MTAPIBase
    {
        public MTCommonBase(MTAsyncConnect connect) : base(connect) { }
        /// <summary>
        /// send request common_get
        /// </summary>
        /// <param name="common">config from MT5 server</param>
        /// <returns></returns>
        public MTRetCode CommonGet(out MTConCommon common)
        {
            common = null;
            //--- get answer
            byte[] answer;
            //--- send request
            if ((answer = Send(MTProtocolConsts.WEB_CMD_COMMON_GET, null)) == null)
            {
                MTLog.Write(MTLogType.Error, "send common get failed");
                return MTRetCode.MT_RET_ERR_NETWORK;
            }
            //---
            string answerStr = MTUtils.GetString(answer);
            if (MTLog.IsWriteDebugLog)
                MTLog.Write(MTLogType.Debug, string.Format("result answer: {0}", answerStr));
            //--- parse answer
            MTRetCode errorCode;
            if ((errorCode = ParseCommonGet(answerStr, out common)) != MTRetCode.MT_RET_OK)
            {
                MTLog.Write(MTLogType.Error, string.Format("parse common get failed: {0}", MTFormat.GetErrorStandart(errorCode)));
                return errorCode;
            }
            //---
            return MTRetCode.MT_RET_OK;
        }
        /// <summary>
        /// check answer from MetaTrader 5 server
        /// </summary>
        /// <param name="answer">answer from MT5 sever</param>
        /// <param name="conCommon">result parsing</param>
        private static MTRetCode ParseCommonGet(string answer, out MTConCommon conCommon)
        {
            int pos = 0;
            conCommon = null;
            //--- get command answer
            string command = MTParseProtocol.GetCommand(answer, ref pos);
            if (command != MTProtocolConsts.WEB_CMD_COMMON_GET)
            {
                MTLog.Write(MTLogType.Error, string.Format("answer command '{0}' is incorrect, wait {1}", command, MTProtocolConsts.WEB_CMD_COMMON_GET));
                return MTRetCode.MT_RET_ERR_DATA;
            }
            //---
            MTCommonGetAnswer commonAnswer = new MTCommonGetAnswer();
            //--- get param
            int posEnd = -1;
            MTAnswerParam param;
            while ((param = MTParseProtocol.GetNextParam(answer, ref pos, ref posEnd)) != null)
            {
                switch (param.Name)
                {
                    case MTProtocolConsts.WEB_PARAM_RETCODE:
                        commonAnswer.RetCode = param.Value;
                        break;
                }
            }
            //---
            MTRetCode errorCode;
            //--- check ret code
            if ((errorCode = MTParseProtocol.GetRetCode(commonAnswer.RetCode)) != MTRetCode.MT_RET_OK)
                return errorCode;
            //--- get json
            if ((commonAnswer.ConfigJson = MTParseProtocol.GetJson(answer, posEnd)) == null)
                return MTRetCode.MT_RET_REPORT_NODATA;
            //--- parsing Json
            conCommon = commonAnswer.GetFromJson();
            //--- parsing empty
            if (conCommon == null)
                return MTRetCode.MT_RET_REPORT_NODATA;
            //---
            return MTRetCode.MT_RET_OK;
        }
    }
    /// <summary>
    /// answer on request common_get
    /// </summary>
    internal class MTCommonGetAnswer : MTBaseAnswerJson
    {
        /// <summary>
        /// From json get class MT5ConTime
        /// </summary>
        public MTConCommon GetFromJson()
        {
            try
            {
                return JsonConvert.DeserializeObject<MTConCommon>(ConfigJson);
            }
            catch (Exception e)
            {
                MTLog.Write(MTLogType.Error, string.Format("parsing common config from json failed, {0}", e));
            }
            return null;
        }
    }
    /// <summary>
    /// class parsin from json to MTConCommon
    /// </summary>
    internal class MTConCommonConverter : JavaScriptConverter
    {
        private static readonly Type[] m_SupportedTypes = new[] { typeof(MTConCommon) };
        public override IEnumerable<Type> SupportedTypes { get { return m_SupportedTypes; } }
        /// <summary>
        /// Deserialize from MT server json
        /// </summary>
        /// <param name="dictionary">data from json</param>
        /// <param name="type">type</param>
        /// <param name="serializer">class serializator</param>
        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            if (dictionary == null)
                return null;
            //---
            MTConCommon obj = new MTConCommon();
            //--- 
            if (dictionary.ContainsKey("Name"))
                obj.Name = MTDataHelper.GetString(dictionary["Name"]);
            //--- 
            if (dictionary.ContainsKey("Owner"))
                obj.Owner = MTDataHelper.GetString(dictionary["Owner"]);
            //---
            if (dictionary.ContainsKey("OwnerHost"))
                obj.OwnerHost = MTDataHelper.GetString(dictionary["OwnerHost"]);
            //---
            if (dictionary.ContainsKey("OwnerID"))
                obj.OwnerID = MTDataHelper.GetString(dictionary["OwnerID"]);
            //---
            if (dictionary.ContainsKey("OwnerEmail"))
                obj.OwnerEmail = MTDataHelper.GetString(dictionary["OwnerEmail"]);
            //---
            if (dictionary.ContainsKey("Product"))
                obj.Product = MTDataHelper.GetString(dictionary["Product"]);
            //---
            if (dictionary.ContainsKey("ExpirationLicense"))
                obj.ExpirationLicense = MTDataHelper.GetInt32(dictionary["ExpirationLicense"]);
            //---
            if (dictionary.ContainsKey("ExpirationSupport"))
                obj.ExpirationSupport = MTDataHelper.GetInt32(dictionary["ExpirationSupport"]);
            //---
            if (dictionary.ContainsKey("LimitTradeServers"))
                obj.LimitTradeServers = MTDataHelper.GetInt32(dictionary["LimitTradeServers"]);
            //---
            if (dictionary.ContainsKey("LimitWebServers"))
                obj.LimitWebServers = MTDataHelper.GetInt32(dictionary["LimitWebServers"]);
            //---
            if (dictionary.ContainsKey("LimitAccounts"))
                obj.LimitAccounts = MTDataHelper.GetInt32(dictionary["LimitAccounts"]);
            //---
            if (dictionary.ContainsKey("LimitDeals"))
                obj.LimitDeals = MTDataHelper.GetInt32(dictionary["LimitDeals"]);
            //---
            if (dictionary.ContainsKey("LimitGroups"))
                obj.LimitGroups = MTDataHelper.GetInt32(dictionary["LimitGroups"]);
            //---
            if (dictionary.ContainsKey("LiveUpdateMode"))
                obj.LiveUpdateMode = MTDataHelper.GetInt32(dictionary["LiveUpdateMode"]);
            //---
            return obj;
        }
        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            return null;
        }

    }

}
